﻿using LCL.Network.Enthernet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace LCL.NetworkDemo
{
    public partial class FormFileClient : Form
    {
        public FormFileClient()
        {
            InitializeComponent();
        }
        private void FormFileClient_Load(object sender, EventArgs e)
        {
            textBox15.Text = Guid.Empty.ToString();
        }
        #region  Intergration File Client
        private void button1_Click(object sender, EventArgs e)
        {
            //初始化
            IntegrationFileClientInitialization();
        }
        private IntegrationFileClient integrationFileClient;                 // 客户端的核心引擎
        private void IntegrationFileClientInitialization()
        {
            System.Net.IPAddress ipAddress;
            int port;
            if (!System.Net.IPAddress.TryParse(textBox1.Text, out ipAddress))
            {
                MessageBox.Show("Ip输入异常，请重新输入！");
                return;
            }
            if (!int.TryParse(textBox2.Text, out port))
            {
                MessageBox.Show("Ip输入异常，请重新输入！");
                return;
            }
            // 定义连接服务器的一些属性，超时时间，IP及端口信息
            integrationFileClient = new IntegrationFileClient()
            {
                ConnectTimeOut = 50000,                                                      // 连接的超时时间
                ServerIpEndPoint = new System.Net.IPEndPoint(ipAddress, port),            // 服务器的地址
                Token = new Guid(textBox15.Text),                                         // 指定一个令牌（不是必须的）
            };
            // 创建本地文件存储的路径
            string path = Application.StartupPath + @"\Files";
            if (!System.IO.Directory.Exists(path))
            {
                System.IO.Directory.CreateDirectory(path);
            }
            button1.Enabled = false;
            panel2.Enabled = true;
        }
        private void button2_Click(object sender, EventArgs e)
        {
            // 选择文件
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    textBox3.Text = ofd.FileName;
                }
            }
        }
        #endregion
        #region Upload File
        private void button3_Click(object sender, EventArgs e)
        {
            // 开始上传
            if (!string.IsNullOrEmpty(textBox3.Text))
            {
                if (!System.IO.File.Exists(textBox3.Text))
                {
                    MessageBox.Show("选择的文件不存在，退出！");
                    return;
                }
                // 点击开始上传，此处按照实际项目需求放到了后台线程处理，事实上这种耗时的操作就应该放到后台线程
                System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart((ThreadUploadFile)));
                thread.IsBackground = true;
                thread.Start(textBox3.Text);
                button3.Enabled = false;
                progressBar1.Value = 0;
            }
            else
            {
                MessageBox.Show("Please Select a File");
            }
        }
        private void ThreadUploadFile(object filename)
        {
            if (filename is string)
            {
                string fileName = (string)filename;
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
                // 开始正式上传，关于三级分类，下面只是举个例子，上传成功后去服务器端寻找文件就能明白
                Result result = integrationFileClient.UploadFile(
                    fileName,                       // 需要上传的原文件的完整路径，上传成功还需要个条件，该文件不能被占用
                    fileInfo.Name,                  // 在服务器存储的文件名，带后缀，一般设置为原文件的文件名，当然您也可以重新设置名字
                    textBox_upload_factory.Text,    // 第一级分类，指示文件存储的类别，对应在服务器端存储的路径不一致
                    textBox_upload_group.Text,      // 第二级分类，指示文件存储的类别，对应在服务器端存储的路径不一致
                    textBox_upload_id.Text,         // 第三级分类，指示文件存储的类别，对应在服务器端存储的路径不一致
                    textBox_upload_tag.Text,        // 这个文件的额外描述文本，可以为空（""）
                    textBox_upload_name.Text,       // 文件的上传人，当然你也可以不使用，可以为空（""）
                    UpdateReportProgress            // 文件上传时的进度报告，如果你不需要，指定为NULL就行，一般文件比较大，带宽比较小，都需要进度提示
                    );
                // 切换到UI前台显示结果 
                Invoke(new Action<Result>(operateResult =>
                {
                    button3.Enabled = true;
                    if (result.Success)
                    {
                        MessageBox.Show("文件上传成功！");
                    }
                    else
                    {
                        // 失败原因多半来自网络异常，还有文件不存在，分类名称填写异常
                        MessageBox.Show("文件上传失败：" + result.ToMessageShowString());
                    }
                }), result);
            }
        }
        private void UpdateReportProgress(long sended, long totle)
        {
            if (progressBar1.InvokeRequired)
            {
                progressBar1.Invoke(new Action<long, long>(UpdateReportProgress), sended, totle);
                return;
            }
            // 此处代码是安全的
            int value = (int)(sended * 100L / totle);
            label10.Text = sended + "/" + totle;
            progressBar1.Value = value;
        }
        #endregion
        #region Download File
        private void button4_Click(object sender, EventArgs e)
        {
            // 点击开始下载，此处按照实际项目需求放到了后台线程处理，事实上这种耗时的操作就应该放到后台线程
            System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart((ThreadDownloadFile)));
            thread.IsBackground = true;
            thread.Start(textBox_download_fileName.Text);
            progressBar2.Value = 0;
            button4.Enabled = false;
        }
        private void ThreadDownloadFile(object filename)
        {
            if (filename is string)
            {
                string fileName = (string)filename;
                Result result = integrationFileClient.DownloadFile(
                    fileName,                                              // 文件在服务器上保存的名称，举例123.txt
                    textBox_download_factory.Text,                         // 第一级分类，指示文件存储的类别，对应在服务器端存储的路径不一致
                    textBox_download_group.Text,                           // 第二级分类，指示文件存储的类别，对应在服务器端存储的路径不一致
                    textBox_download_id.Text,                              // 第三级分类，指示文件存储的类别，对应在服务器端存储的路径不一致
                    DownloadReportProgress,                                // 文件下载的时候的进度报告，友好的提示下载进度信息
                    Application.StartupPath + @"\Files\" + filename        // 下载后在文本保存的路径，也可以直接下载到 MemoryStream 的数据流中，或是bitmap中，或是手动选择存储路径
                    );
                // 切换到UI前台显示结果
                Invoke(new Action<Result>(operateResult =>
                {
                    button4.Enabled = true;
                    if (result.Success)
                    {
                        MessageBox.Show("文件下载成功！");
                    }
                    else
                    {
                        // 失败原因多半来自网络异常，还有文件不存在，分类名称填写异常
                        MessageBox.Show("文件下载失败：" + result.ToMessageShowString());
                    }
                }), result);
            }
        }
        private void DownloadReportProgress(long receive, long totle)
        {
            if (progressBar2.InvokeRequired)
            {
                progressBar2.Invoke(new Action<long, long>(DownloadReportProgress), receive, totle);
                return;
            }
            // 此处代码是线程安全的
            int value = (int)(receive * 100L / totle);
            progressBar2.Value = value;
            label9.Text = receive + "/" + totle;
        }
        #endregion
        #region Delete Files
        private void button5_Click(object sender, EventArgs e)
        {
            // 文件的删除不需要放在后台线程，前台即可处理，无论多少大的文件，无论该文件是否在下载中，都是很快删除的
            Result result = integrationFileClient.DeleteFile(
                textBox_delete_fileName.Text,                       // 文件在服务器上保存的名称，举例123.txt
                textBox_delete_factory.Text,                        // 第一级分类，指示文件存储的类别，对应在服务器端存储的路径不一致
                textBox_delete_id.Text,                             // 第二级分类，指示文件存储的类别，对应在服务器端存储的路径不一致
                textBox_download_id.Text                            // 第三级分类，指示文件存储的类别，对应在服务器端存储的路径不一致
                );
            if (result.Success)
            {
                MessageBox.Show("文件删除成功！");
            }
            else
            {
                // 删除失败的原因除了一般的网络问题，还有因为服务器的文件不存在，会在Message里有显示。
                // file not exsist or net work exception
                MessageBox.Show("文件删除失败，原因：" + result.ToMessageShowString());
            }
        }
        #endregion
        #region  浏览服务器文件
        private void button6_Click(object sender, EventArgs e)
        {
            //刷新
            treeView1.Nodes[0].Nodes.Clear();
            FillNodeByFactoryGroupId(treeView1.Nodes[0], "", "", "", 1);
        }
        private void FillNodeFilesByFactoryGroupId(TreeNode root, string factory, string group, string id)
        {
            root.Nodes.Clear();
            GroupFileItem[] files;
            Result read = integrationFileClient.DownloadPathFileNames(out files, factory, group, id);
            if (read.Success)
            {
                foreach (var item in files)
                {
                    TreeNode node = new TreeNode(item.FileName);
                    node.Tag = item;
                    root.Nodes.Add(node);
                }
                // root.ExpandAll( ); occur an exception ?? I don't know
            }
            else
            {
                MessageBox.Show(read.ToMessageShowString());
            }
        }
        private void FillNodeByFactoryGroupId(TreeNode root, string factory, string group, string id, int grade)
        {
            root.Nodes.Clear();
            string[] folders;
            Result read = integrationFileClient.DownloadPathFolders(out folders, factory, group, id);
            if (read.Success)
            {
                foreach (var item in folders)
                {
                    TreeNode node = new TreeNode(item);
                    node.Tag = grade;
                    node.Nodes.Add(new TreeNode());
                    root.Nodes.Add(node);
                }
                // root.ExpandAll( ); occur an exception ?? I don't know
            }
            else
            {
                MessageBox.Show(read.ToMessageShowString());
            }
        }
        private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            TreeNode node = e.Node;
            if (node.Tag != null)
            {
                if (node.Tag is int)
                {
                    int grade = (int)node.Tag;
                    if (grade == 1)
                    {
                        FillNodeByFactoryGroupId(node, node.Text, "", "", 2);
                    }
                    else if (grade == 2)
                    {
                        FillNodeByFactoryGroupId(node, node.Parent.Text, node.Text, "", 3);
                    }
                    else if (grade == 3)
                    {
                        FillNodeFilesByFactoryGroupId(node, node.Parent.Parent.Text, node.Parent.Text, node.Text);
                    }
                }
            }
        }
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeNode node = e.Node;
            if (node.Tag != null)
            {
                if (node.Tag is GroupFileItem)
                {
                    GroupFileItem fileItem = (GroupFileItem)node.Tag;
                    textBox_file_fileName.Text = fileItem.FileName;
                    textBox_file_fileSize.Text = fileItem.FileSize.ToString();
                    textBox_file_date.Text = fileItem.UploadTime.ToString();
                    textBox_file_dowloadTimes.Text = fileItem.DownloadTimes.ToString();
                    textBox_file_upload.Text = fileItem.Owner;
                    textBox_file_tag.Text = fileItem.Description;
                }
            }
        }
        #endregion
    }
}
